<script src="../../dist/vue.global.js"></script>

<!-- DemoGrid component template -->
<script type="text/x-template" id="grid-template">
  <table v-if="filteredData.length">
    <thead>
      <tr>
        <th v-for="key in columns"
          @click="sortBy(key)"
          :class="{ active: state.sortKey == key }">
          {{ capitalize(key) }}
          <span class="arrow" :class="state.sortOrders[key] > 0 ? 'asc' : 'dsc'">
          </span>
        </th>
      </tr>
    </thead>
    <tbody>
      <tr v-for="entry in filteredData">
        <td v-for="key in columns">
          {{entry[key]}}
        </td>
      </tr>
    </tbody>
  </table>
  <p v-else>No matches found.</p>
</script>
<!-- DemoGrid component script -->
<script>
  const { reactive, computed } = Vue

  const capitalize = str => str.charAt(0).toUpperCase() + str.slice(1)

  const DemoGrid = {
    template: '#grid-template',
    props: {
      data: Array,
      columns: Array,
      filterKey: String,
    },
    setup(props) {
      const state = reactive({
        sortKey: '',
        sortOrders: props.columns.reduce((o, key) => ((o[key] = 1), o), {}),
      })

      const filteredData = computed(() => {
        let { data, filterKey } = props
        if (filterKey) {
          filterKey = filterKey.toLowerCase()
          data = data.filter(row => {
            return Object.keys(row).some(key => {
              return String(row[key]).toLowerCase().indexOf(filterKey) > -1
            })
          })
        }
        const { sortKey } = state
        if (sortKey) {
          const order = state.sortOrders[sortKey]
          data = data.slice().sort((a, b) => {
            a = a[sortKey]
            b = b[sortKey]
            return (a === b ? 0 : a > b ? 1 : -1) * order
          })
        }
        return data
      })

      function sortBy(key) {
        state.sortKey = key
        state.sortOrders[key] *= -1
      }

      return {
        state,
        filteredData,
        sortBy,
        capitalize,
      }
    },
  }
</script>

<!-- App template (in DOM) -->
<div id="demo">
  <form id="search">Search <input name="query" v-model="searchQuery" /></form>
  <demo-grid :data="gridData" :columns="gridColumns" :filter-key="searchQuery">
  </demo-grid>
</div>
<!-- App script -->
<script>
  Vue.createApp({
    components: {
      DemoGrid,
    },
    data: () => ({
      searchQuery: '',
      gridColumns: ['name', 'power'],
      gridData: [
        { name: 'Chuck Norris', power: Infinity },
        { name: 'Bruce Lee', power: 9000 },
        { name: 'Jackie Chan', power: 7000 },
        { name: 'Jet Li', power: 8000 },
      ],
    }),
  }).mount('#demo')
</script>

<style>
  body {
    font-family:
      Helvetica Neue,
      Arial,
      sans-serif;
    font-size: 14px;
    color: #444;
  }

  table {
    border: 2px solid #42b983;
    border-radius: 3px;
    background-color: #fff;
  }

  th {
    background-color: #42b983;
    color: rgba(255, 255, 255, 0.66);
    cursor: pointer;
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
  }

  td {
    background-color: #f9f9f9;
  }

  th,
  td {
    min-width: 120px;
    padding: 10px 20px;
  }

  th.active {
    color: #fff;
  }

  th.active .arrow {
    opacity: 1;
  }

  .arrow {
    display: inline-block;
    vertical-align: middle;
    width: 0;
    height: 0;
    margin-left: 5px;
    opacity: 0.66;
  }

  .arrow.asc {
    border-left: 4px solid transparent;
    border-right: 4px solid transparent;
    border-bottom: 4px solid #fff;
  }

  .arrow.dsc {
    border-left: 4px solid transparent;
    border-right: 4px solid transparent;
    border-top: 4px solid #fff;
  }
</style>
